// @Description
// @Author  xiaoyang
// @Date  2022/4/28 2:39 下午

package codec

import (
	"bufio"
	"encoding/json"
	"io"
	"log"
)

type JsonCodec struct {
	conn io.ReadWriteCloser // 连接实例：通过 TCP 或者 Unix 建立 socket 时得到的链接实例
	buf  *bufio.Writer      // buf 是为了防止阻塞而创建的带缓冲的 Writer
	dec  *json.Decoder
	enc  *json.Encoder
}

func (j *JsonCodec) Close() error {
	return j.conn.Close()
}

func (j *JsonCodec) ReadHeader(header *Header) error {
	return j.dec.Decode(header)
}

func (j *JsonCodec) ReadBody(body interface{}) error {
	return j.dec.Decode(body)
}

func (j *JsonCodec) Write(header *Header, body interface{}) (err error) {
	defer func() {
		_ = j.buf.Flush()
		if err != nil {
			_ = j.conn.Close()
		}
	}()

	if err := j.enc.Encode(header); err != nil {
		log.Println("rpc codec : json error encoding header:", err)
		return err
	}

	if err := j.enc.Encode(body); err != nil {
		log.Println("rpc codec : json error encoding body:", err)
		return err
	}

	return nil
}

var (
	// 初始化变量Codec (JsonCodec 实现了 Codec的接口)
	_ Codec = (*JsonCodec)(nil)
)

// NewJsonCodec
/**
 *  @Author yang
 *  @Description 创建编码结构
**/
func NewJsonCodec(conn io.ReadWriteCloser) Codec {
	buf := bufio.NewWriter(conn)
	return &JsonCodec{
		buf:  buf,
		conn: conn,
		dec:  json.NewDecoder(conn),
		enc:  json.NewEncoder(buf),
	}
}
